#include "PlayState.h"

SGE_Sound CuckooSound;
SGE_Sound ExplosionSound;
SGE_Sound BugleSound;

PlayState::PlayState(GameContext& gc)
	:GameState(gc)
	,spawnDelay(3.0f)
	,spawnDelay2(10.0f)
	,spawnDelay3(50.0f)
	,kMaxEgg(999)
	,EggIndex(0)
	,kMaxCuckoo(999)
	,CuckooIndex(0)
	,kMaxBadEgg(3)
	,BadEggIndex(0)
	,kMaxExplosion(3)
	,ExplosionIndex(0)
	,kMaxGoldEgg(1)
	,GoldEggIndex(0)
	,kMaxBugle(1)
	,BugleIndex(0)
	,GoldGet(false)
	,Goldtimer(0)
{
	Score = 0;
	Life = 3;
}

PlayState::~PlayState(void)
{
}

void PlayState::Load()
{
	if (mGameContext.GetLevel() == 1)
	{
		mCase.Load();
		mCase.SetPosition(SVector2(400.0f, 650.0f));
	}
	else
	{
		mCase2.Load();
		mCase2.SetPosition(SVector2(300.0f, 650.0f));
	}
	
	int numChickens = 0;
	if (mGameContext.GetLevel() == 1)
	{
		numChickens = 4;
	}
	else
	{
		numChickens = 6;
	}

	mChar.resize(numChickens);
	float gap = 735.0f / (numChickens - 1);
	for (int i = 0; i < numChickens; ++i)
	{
		mChar[i].Load();
		mChar[i].SetPosition(SVector2(150.0f + (gap * i), 80.0f));
	}
	
	for(int i = 0; i < kMaxEgg; ++i)
	{
		mEgg[i].Load();
	}

	for(int i = 0; i < kMaxBadEgg; ++i)
	{
		mBadEgg[i].Load();
	}

	for(int i = 0; i < kMaxGoldEgg; ++i)
	{
		mGoldEgg[i].Load();
	}

	CuckooSound.Load("cuckoo.mp3");
	ExplosionSound.Load("explosion.wav");
	BugleSound.Load("Bugle.wav");

	char levelName[256];
	char texturePackName[256];
	sprintf_s(levelName, 256, "level0%d.txt", mGameContext.GetLevel());
	sprintf_s(texturePackName, 256, "texturepack0%d.txt", mGameContext.GetLevel());
	mMap.Load(levelName, texturePackName);

	mFont.Load(24, true);
}

void PlayState::Unload()
{
	if (mGameContext.GetLevel() == 1)
	{
		mCase.Unload();
	}
	else
	{
		mCase2.Unload();
	}

	for(int i = 0; i < (int)mChar.size(); ++i)
	{
		mChar[i].Unload();
	}

	for(int i = 0; i < kMaxEgg; ++i)
	{
		mEgg[i].Unload();
	}

	for(int i = 0; i < kMaxBadEgg; ++i)
	{
		mBadEgg[i].Unload();
	}

	for(int i = 0; i < kMaxGoldEgg; ++i)
	{
		mGoldEgg[i].Unload();
	}

	mMap.Unload();
	CuckooSound.Unload();
	ExplosionSound.Unload();
	BugleSound.Unload();
	mFont.Unload();
}

NextState PlayState::Update(float deltaTime)
{
	if (mGameContext.GetLevel() == 1)
	{
		mCase.Update(deltaTime);
	}
	else
	{
		mCase2.Update(deltaTime);
	}

	for(int i = 0; i < (int)mChar.size(); ++i)
	{
		mChar[i].Update(deltaTime, mMap);
		SpawnEgg(deltaTime, mChar[i], GoldGet);
		SpawnBadEgg(deltaTime, mChar[i]);
		SpawnGoldEgg(deltaTime, mChar[i]);
	}

	for(int i = 0; i  < kMaxEgg; ++i)
	{
		mEgg[i].Update(deltaTime);
	}

	CheckCollision();

	for(int i = 0; i < kMaxCuckoo; ++i)
	{
		Cuckoo[i].Update(deltaTime);
	}

	for(int i = 0; i < kMaxBadEgg; ++i)
	{
		mBadEgg[i].Update(deltaTime);
	}

	for(int i = 0; i < kMaxExplosion; ++i)
	{
		Explosion[i].Update(deltaTime);
	}

	CheckCollision2();

	for(int i = 0; i < kMaxGoldEgg; ++i)
	{
		mGoldEgg[i].Update(deltaTime);
	}

	CheckCollision3();

	NextState nextState = None;


	if(Input_IsKeyPressed(Keys::ESCAPE))
	{
		nextState = Frontend;
	}
	if(Life == 0)
	{
		nextState = GameOver;
	}
	if(GoldGet)
	{
		Goldtimer += deltaTime;
	}
	if(Goldtimer == 1)
	{
		GoldGet = false;
	}
	return nextState;
}

void PlayState::SpawnEgg(float deltaTime, const CharacterIdle& chicken, bool gold)
{
	spawnDelay -= deltaTime;
	if(spawnDelay <= 0.0f)
	{
		//It's time to spawn!
		if( !mEgg[EggIndex].IsActive())
		{
			const int kWinWidth = IniFile_GetInt("WinWidth", 800);
			const float posX = kWinWidth * RandomFloat(0.1f,0.9f);
			const float posY = 0.0f;
			mEgg[EggIndex].Spawn(chicken.GetPosition(), SVector2(0.0f, 200.0f));
			EggIndex = (EggIndex + 1) % kMaxEgg;

			//Reset deklay time
			if(gold)
			{
				spawnDelay = 1.5f;
			}
			else
			{
				spawnDelay = RandomFloat(3.0f, 4.0f);
			}
		}
	}
}

void PlayState::SpawnBadEgg(float deltaTime, const CharacterIdle& chicken)
{
	spawnDelay2 -= deltaTime;
	if(spawnDelay2 <= 0.0f)
	{
		//It's time to spawn!
		if( !mBadEgg[BadEggIndex].IsActive())
		{
			const int kWinWidth = IniFile_GetInt("WinWidth", 800);
			const float posX = kWinWidth * RandomFloat(0.1f,0.9f);
			const float posY = 0.0f;
			if (mGameContext.GetLevel() == 1)
			{
				mBadEgg[BadEggIndex].Spawn(chicken.GetPosition(), SVector2(0.0f, 300.0f));
			}
			else
			{
				mBadEgg[BadEggIndex].Spawn(chicken.GetPosition(), SVector2(0.0f, 400.0f));
			}

			BadEggIndex = (BadEggIndex + 1) % kMaxBadEgg;

			//Reset deklay time
			if (mGameContext.GetLevel() == 1)
			{
				spawnDelay2 = RandomFloat(4.0f, 8.0f);
			}
			else
			{
				spawnDelay2 = RandomFloat(2.0f, 6.0f);
			}
		}
	}
}

void PlayState::SpawnGoldEgg(float deltaTime, const CharacterIdle& chicken)
{
	spawnDelay3 -= deltaTime;
	if(spawnDelay3 <= 0.0f)
	{
		//It's time to spawn!
		if( !mGoldEgg[GoldEggIndex].IsActive())
		{
			for(int i = 0; i < (int)mChar.size(); ++i)
			{
				mChar[i].Play();
			}
			
			const int kWinWidth = IniFile_GetInt("WinWidth", 800);
			const float posX = kWinWidth * RandomFloat(0.1f,0.9f);
			const float posY = 0.0f;
			mGoldEgg[GoldEggIndex].Spawn(chicken.GetPosition(), SVector2(0.0f, 600.0f));
			GoldEggIndex = (GoldEggIndex + 1) % kMaxGoldEgg;

			//Reset deklay time
			if (mGameContext.GetLevel() == 1)
			{
				spawnDelay3 = RandomFloat(100.0f, 150.0f);
			}
			else
			{
				spawnDelay3 = RandomFloat(130.0f, 200.0f);
			}
		}
	}
}

void PlayState::Render()
{
	const int kWinWidth = IniFile_GetInt("WinWidth", 800);
	const int kWinHeight = IniFile_GetInt("WinHeight", 600);

	SVector2 viewTarget = mCase.GetPosition();
	SVector2 viewTarget2 = mCase2.GetPosition();

	SVector2 viewOffset;
	viewOffset.x = viewTarget.x - (kWinWidth * 0.5f);
	viewOffset.y = viewTarget.y - (kWinHeight * 0.5f);

	SVector2 viewOffset2;
	viewOffset2.x = viewTarget2.x - (kWinWidth * 0.5f);
	viewOffset2.y = viewTarget2.y - (kWinHeight * 0.5f);

	SVector2 limit;
	limit.x = (float)mMap.GetWidth() - kWinWidth;
	limit.y = (float)mMap.GetHeight() - kWinHeight;

	viewOffset.x = Clamp(viewOffset.x, 0.0f, limit.x);
	viewOffset.y = Clamp(viewOffset.y, 0.0f, limit.y);

	viewOffset2.x = Clamp(viewOffset2.x, 0.0f, limit.x);
	viewOffset2.y = Clamp(viewOffset2.y, 0.0f, limit.y);

	mMap.Render(viewOffset);
	mMap.Render(viewOffset2);

	if (mGameContext.GetLevel() == 1)
	{
		mCase.Render(viewOffset);
	}
	else
	{
		mCase2.Render(viewOffset2);
	}

	for(int i = 0; i < (int)mChar.size(); ++i)
	{
		if (mGameContext.GetLevel() == 1)
		{
			mChar[i].Render(viewOffset);
		}
		else
		{
			mChar[i].Render(viewOffset2);
		}
	}

	for(int i = 0; i < kMaxEgg; ++i)
	{
		if (mGameContext.GetLevel() == 1)
		{
			mEgg[i].Render(viewOffset);
		}
		else
		{
			mEgg[i].Render(viewOffset2);
		}
	}

	for(int i = 0; i < kMaxCuckoo; ++i)
	{
		Cuckoo[i].Render(true);
	}

	for(int i = 0; i < kMaxExplosion; ++i)
	{
		Explosion[i].Render(true);
	}

	for(int i = 0; i < kMaxBadEgg; ++i)
	{
		if (mGameContext.GetLevel() == 1)
		{
			mBadEgg[i].Render(viewOffset);
		}
		else
		{
			mBadEgg[i].Render(viewOffset2);
		}
	}

	for(int i = 0; i < kMaxGoldEgg; ++i)
	{
		if (mGameContext.GetLevel() == 1)
		{
			mGoldEgg[i].Render(viewOffset);
		}
		else
		{
			mGoldEgg[i].Render(viewOffset2);
		}
	}

	char buffer[128];
	char buffer2[128];
	sprintf_s(buffer, 128, "Score : %d", Score);
	sprintf_s(buffer2, 128, "Life : %d", Life);
	mFont.SetColor(155, 255, 0);
	mFont.SetColor(255,0, 0);
	mFont.Print(buffer, 460, 20);
	mFont.Print(buffer2, 460, 40);
}

void PlayState::CheckCollision()
{
	for(int e = 0; e < kMaxEgg; ++e)
	{
		if(mEgg[e].IsActive())
		{
			if (mGameContext.GetLevel() == 1)
			{
				SCircle eCircle = mEgg[e].GetBoundingCircle();
				SCircle cCircle = mCase.GetBoundingCircle();
				float xDiff = eCircle.center.x - cCircle.center.x;
				float yDiff = eCircle.center.y - cCircle.center.y;
				float dist = sqrt(xDiff * xDiff + yDiff * yDiff);
				float radii = eCircle.radius + cCircle.radius;

				if(dist <= radii)
				{
					mEgg[e].Kill();
					Score = Score + 10;
					Cuckoo[CuckooIndex].SetPosition(eCircle.center);
					Cuckoo[CuckooIndex].Start(100.0f,true);
					CuckooIndex = (CuckooIndex+1) % kMaxCuckoo;

					CuckooSound.Play();

					break;
				}
			}
			else
			{
				SCircle eCircle2 = mEgg[e].GetBoundingCircle();
				SCircle cCircle2 = mCase2.GetBoundingCircle();
				float xDiff2 = eCircle2.center.x - cCircle2.center.x;
				float yDiff2 = eCircle2.center.y - cCircle2.center.y;
				float dist2 = sqrt(xDiff2 * xDiff2 + yDiff2 * yDiff2);
				float radii2 = eCircle2.radius + cCircle2.radius;
			
				if(dist2 <= radii2)
				{
						mEgg[e].Kill();
						Score = Score + 10;
						Cuckoo[CuckooIndex].SetPosition(eCircle2.center);
						Cuckoo[CuckooIndex].Start(100.0f,true);
						CuckooIndex = (CuckooIndex+1) % kMaxCuckoo;

						CuckooSound.Play();

						break;
				}
			}
		}
	}
}

void PlayState::CheckCollision2()
{
	for(int e = 0; e < kMaxBadEgg; ++e)
	{
		if(mBadEgg[e].IsActive())
		{
			if (mGameContext.GetLevel() == 1)
			{
				SCircle eCircle = mBadEgg[e].GetBoundingCircle();
				SCircle cCircle = mCase.GetBoundingCircle();
				float xDiff = eCircle.center.x - cCircle.center.x;
				float yDiff = eCircle.center.y - cCircle.center.y;
				float dist = sqrt(xDiff * xDiff + yDiff * yDiff);
				float radii = eCircle.radius + cCircle.radius;

				if(dist <= radii)
				{
					mBadEgg[e].Kill();
					Life = Life - 1;
					Explosion[ExplosionIndex].SetPosition(eCircle.center);
					Explosion[ExplosionIndex].Start(100.0f,true);
					ExplosionIndex = (ExplosionIndex+1) % kMaxExplosion;

					ExplosionSound.Play();

					break;
				}
			}
			else
			{
				SCircle eCircle2 = mBadEgg[e].GetBoundingCircle();
				SCircle cCircle2 = mCase2.GetBoundingCircle();
				float xDiff2 = eCircle2.center.x - cCircle2.center.x;
				float yDiff2 = eCircle2.center.y - cCircle2.center.y;
				float dist2 = sqrt(xDiff2 * xDiff2 + yDiff2 * yDiff2);
				float radii2 = eCircle2.radius + cCircle2.radius;
			
				if(dist2 <= radii2)
				{
					mBadEgg[e].Kill();
					Life = Life - 1;
					Explosion[ExplosionIndex].SetPosition(eCircle2.center);
					Explosion[ExplosionIndex].Start(100.0f,true);
					ExplosionIndex = (ExplosionIndex+1) % kMaxExplosion;

					ExplosionSound.Play();

					break;
				}
			}
		}
	}
}

void PlayState::CheckCollision3()
{
	for(int e = 0; e < kMaxGoldEgg; ++e)
	{
		if(mGoldEgg[e].IsActive())
		{
			if (mGameContext.GetLevel() == 1)
			{
				SCircle eCircle = mGoldEgg[e].GetBoundingCircle();
				SCircle cCircle = mCase.GetBoundingCircle();
				float xDiff = eCircle.center.x - cCircle.center.x;
				float yDiff = eCircle.center.y - cCircle.center.y;
				float dist = sqrt(xDiff * xDiff + yDiff * yDiff);
				float radii = eCircle.radius + cCircle.radius;

				if(dist <= radii)
				{
					mGoldEgg[e].Kill();
					GoldGet = true;
					Bugle[BugleIndex].SetPosition(eCircle.center);
					Bugle[BugleIndex].Start(100.0f,true);
					BugleIndex = (BugleIndex+1) % kMaxBugle;

					BugleSound.Play();

					for(int i = 0; i < (int)mChar.size(); ++i)
					{
						mChar[i].Stop();
					}

					break;
				}
				else
				{
					GoldGet = false;

					for(int i = 0; i < (int)mChar.size(); ++i)
					{
						mChar[i].Stop();
					}
				}
			}
			else
			{
				SCircle eCircle2 = mGoldEgg[e].GetBoundingCircle();
				SCircle cCircle2 = mCase2.GetBoundingCircle();
				float xDiff2 = eCircle2.center.x - cCircle2.center.x;
				float yDiff2 = eCircle2.center.y - cCircle2.center.y;
				float dist2 = sqrt(xDiff2 * xDiff2 + yDiff2 * yDiff2);
				float radii2 = eCircle2.radius + cCircle2.radius;
			
				if(dist2 <= radii2)
				{
					mGoldEgg[e].Kill();
					GoldGet = true;
					Bugle[BugleIndex].SetPosition(eCircle2.center);
					Bugle[BugleIndex].Start(100.0f,true);
					BugleIndex = (BugleIndex+1) % kMaxBugle;

					BugleSound.Play();

					for(int i = 0; i < (int)mChar.size(); ++i)
					{
						mChar[i].Stop();
					}

					break;
				}
				else
				{
					GoldGet = false;

					for(int i = 0; i < (int)mChar.size(); ++i)
					{
						mChar[i].Stop();
					}
				}
			}
		}
	}
}